#include <linux/module.h>
#include <linux/fs.h>
#include <linux/uaccess.h>
#include <linux/mutex.h>

#define DEV_NAME "mutexdemo"
#define BUF_LEN 128

static int major;
static char kernel_buf[BUF_LEN];           // 驱动中的共享缓冲区
static struct mutex buffer_mutex;          // 用于保护 kernel_buf 的互斥锁

// open 和 release 是可选的，这里我们留空实现
static int my_open(struct inode *inode, struct file *file) { return 0; }
static int my_release(struct inode *inode, struct file *file) { return 0; }

// 用户程序调用 read() -> 驱动执行 my_read()
static ssize_t my_read(struct file *file, char __user *buf, size_t len, loff_t *ppos)
{
    ssize_t ret;
    //mutex_lock(&buffer_mutex);

    size_t data_len = strlen(kernel_buf);
    if (len > data_len)
        len = data_len;

    if (copy_to_user(buf, kernel_buf, len))
        ret = -EFAULT;
    else
        ret = len;

    printk(KERN_INFO "read buffer content: [%s]\n", kernel_buf);

    //mutex_unlock(&buffer_mutex);
    return ret;
}

// 用户程序调用 write() -> 驱动执行 my_write()
static ssize_t my_write(struct file *file, const char __user *buf, size_t len, loff_t *ppos)
{
    ssize_t ret;

    if (len >= BUF_LEN)  // 防止缓冲区溢出
        return -EINVAL;

    // 加锁
    //mutex_lock(&buffer_mutex);

    // 拷贝用户数据到 kernel_buf
    if (copy_from_user(kernel_buf, buf, len)) {
        ret = -EFAULT;
    } else {
        kernel_buf[len] = '\0';  // 确保字符串结尾
        printk(KERN_INFO "[mutexdemo] Received: %s\n", kernel_buf);
        ret = len;
    }

    //mutex_unlock(&buffer_mutex);
    return ret;
}

// file_operations 结构体
static const struct file_operations fops = {
    .owner = THIS_MODULE,
    .open = my_open,
    .release = my_release,
    .read = my_read,
    .write = my_write,
};

// 模块加载时初始化
static int __init mutexmod_init(void)
{
    //mutex_init(&buffer_mutex);  // 初始化互斥锁

    major = register_chrdev(0, DEV_NAME, &fops);
    if (major < 0)
        return major;

    printk(KERN_INFO "mutexdemo device registered, major=%d\n", major);
    return 0;
}

// 卸载模块时清理
static void __exit mutexmod_exit(void)
{
    unregister_chrdev(major, DEV_NAME);
    printk(KERN_INFO "mutexdemo device unregistered.\n");
}

module_init(mutexmod_init);
module_exit(mutexmod_exit);

MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Linux内核 mutex示例驱动");